package zen_group.mdl;

import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import zen_group.mdl.Part.Fault;
import zen_group.mdl.Part.Income;

public
class XlsPartWriter
{
    public
    XlsPartWriter(File destination)
    {
        mFile   = destination;
    }


    public void
    write(HashMap<Part, Integer> results, int simulationCount)
            throws Exception
    {
        XlsWriter   w   = new XlsWriter(mFile);

        w.setSheetName(simulationCount + " simuliacijų rezultatai")
                .headCell("Detalė").setColumnWidth(300)
                .headCell("Rekomenduojama turėti").setColumnWidth(150);

        for (Map.Entry<Part, Integer> e : sortedList(results))
        {
            w
                .newLine()
                .cell(e.getKey().title())
                .cell(e.getValue());
        }

        w.write();
    }



    public void
    write(HashMap<Part, Part.Period> results)
            throws Exception
    {
        long		now		= System.currentTimeMillis();
        final long	day		= 60 * 60 * 24 * 1000; // in milliseconds
        XlsWriter   writer	= new XlsWriter(mFile);

        writer.setSheetName("Vienos simuliacijos rezultatai");

        int	line		= 0;
        int columns[]	= {0, 1, 5, 8};

        for (Map.Entry<Part, Part.Period> item : sortedList(results))
        {
            // headings
            int partTitleLine	= line++;
            int	topHeadingsLine	= line++;
            int headingsLine	= line++;
            int resultsLine		= line++;

            writer
                .cellAbsPos(columns[0])
                    .headCell(item.getKey().title()).merge(9)
                        //.setRowHeight(30)
                .rowAbsPos(topHeadingsLine)
                .cellAbsPos(columns[0])
                    .cell("").setColumnWidth(30)
                .cellAbsPos(columns[1])
                    .headCell("REZERVO NAUDINGUMAS").merge(2)
                .rowAbsPos(headingsLine)
                .cellAbsPos(columns[1])
                    .headCell("Kiekis")
                    .headCell("Ek. nauda")
                        .setColumnWidth(80)
                    .headCell("Pelnas")
                        .setColumnWidth(80)
                    .cell("").setColumnWidth(30)
                .rowAbsPos(topHeadingsLine)
                .cellAbsPos(columns[2])
                    .headCell("TRŪKUMAI").merge(1)
                .rowAbsPos(headingsLine)
                .cellAbsPos(columns[2])
                    .headCell("Kiekis")
                    .headCell("Kartai")
                    .cell("").setColumnWidth(30)
                .rowAbsPos(topHeadingsLine)
                .cellAbsPos(columns[3])
                    .headCell("GEDIMAI").merge(1)
                .rowAbsPos(headingsLine)
                .cellAbsPos(columns[3])
                    .headCell("Data")
                        .setColumnWidth(80)
                    .headCell("Kartai")
                .rowAbsPos(resultsLine);

            // faults
            int faultResultsLine	= resultsLine;
            for (Fault fault : item.getValue().faults())
            {
                Date	date	= new Date(now + ((long)fault.day() * day));
                writer
                    .rowAbsPos(faultResultsLine++)
                    .cellAbsPos(columns[3])
                        .cell(date)
                        .cell(fault.count());
            }

            writer.rowAbsPos(faultResultsLine).cellAbsPos(columns[3])
                .cell("Iš viso:");

            if (item.getValue().faults().isEmpty())
            {
                writer.cell(0);
            }
            else
            {
                // :TODO: calculate column letter
                writer.cellFormula(
                        "SUM(J" + (resultsLine + 1)
                        + ":J" + (faultResultsLine++) + ")"
                    );
            }

            // deficits
            int deficitResultsLine	= resultsLine;
            for (Map.Entry<Integer, Integer> deficit
                    : item.getValue().deficits().entrySet())
                    //: sortedList(item.getValue().deficits()))
            {
                writer
                    .rowAbsPos(deficitResultsLine++)
                    .cellAbsPos(columns[2])
                        .cell(deficit.getKey())
                        .cell(deficit.getValue());
            }

            // incomes
            int incomeResultsLine	= resultsLine;
            int incomeCount			= 0;
            for (Income income : item.getValue().income())
            {
                writer
                    .rowAbsPos(incomeResultsLine++)
                    .cellAbsPos(columns[1])
                        .cell(incomeCount++)
                        .cell(income.all())
                        .cell(income.pure());
            }

            writer
                .rowPos(2)
                .cellAbsPos(columns[1])
                    .headCell("Rekomenduojama").merge(1)
                .rowPos(1)
                .cellAbsPos(columns[1])
                    .cell(item.getValue().income().size() - 1);
            incomeResultsLine	+= 3;

            line	= Math.max(Math.max(faultResultsLine, deficitResultsLine)
                    , incomeResultsLine);
            writer.rowAbsPos(++line);
        }

        writer.write();
    }


    static private <Key extends Comparable<Key>,
            Val extends Comparable<Val>>
    List<Map.Entry<Key, Val>>
    sortedList(HashMap<Key, Val> map)
    {
        List<Map.Entry<Key, Val>>  list    =
                new Vector<Map.Entry<Key, Val>>(map.entrySet());

        Collections.sort(list, new Comparator<Map.Entry<Key, Val>>()
        {
            public int
            compare(Map.Entry<Key, Val> e1,
                    Map.Entry<Key, Val> e2)
            {
                int cmp = e2.getValue().compareTo(e1.getValue());
                if (0 == cmp)
                    cmp = e1.getKey().compareTo(e2.getKey());
                return cmp;
            }
        });

        return list;
    }


    private File    mFile;
}
